#include "tcp_client.h"
#include "esp_log.h"
#include <string.h>
#include <errno.h>
#include "uart_iot.h"
#include "esp_timer.h"
#include <freertos/task.h>
#include <sys/socket.h>
#include <freertos/FreeRTOS.h>
#include <freertos/timers.h>

static const char *TAG = "TCPClient";
#define CORRECT 1

// 默认配置
static const TcpClientConfig DEFAULT_CONFIG = {
    .heartbeat_interval_ms = 1000,
    .send_queue_size = 32,
    .recv_buffer_size = 2048,
    .send_timeout_ms = 2000,
    .reconnect_interval_ms = 2000
};

// 全局变量
static int tcp_socket = -1;
static char *server_ip = NULL;
static int server_port = 0;
static TaskHandle_t send_task_handle = NULL;
static TaskHandle_t recv_task_handle = NULL;
static QueueHandle_t send_queue = NULL;
static SemaphoreHandle_t socket_mutex = NULL;
static SemaphoreHandle_t state_mutex = NULL;
static TimerHandle_t heartbeat_timer = NULL;
static TcpConnectionState connection_state = TCP_STATE_DISCONNECTED;
static TcpClientConfig client_config = DEFAULT_CONFIG;
const char* welcome_message = "welcome to server!";
static const size_t welcome_msg_len = 18; // strlen(welcome_message)

// 添加所有静态函数的声明
static bool tcp_connect_to_server(void);
static void tcp_start_heartbeat(void);
static void tcp_stop_heartbeat(void);
static void tcp_send_heartbeat(TimerHandle_t xTimer);
static void tcp_recv_task(void *pvParameters);
static void tcp_connection_callback(void *arg, err_t err);
static void tcp_reconnection_callback(void *arg, err_t err);
// static void tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_error_callback(void *arg, err_t err);

// 设置连接状态 (线程安全)
static void set_connection_state(TcpConnectionState new_state) {
    xSemaphoreTake(state_mutex, portMAX_DELAY);
    connection_state = new_state;
    xSemaphoreGive(state_mutex);
    
    ESP_LOGI(TAG, "Connection state changed to: %d", new_state);
}

// 发送心跳包
static void tcp_send_heartbeat(TimerHandle_t xTimer) {
    if (tcp_get_connection_state() != TCP_STATE_CONNECTED) return;

    const char heartbeat[] = "HEARTBEAT";
    const size_t len = strlen(heartbeat);
    
    if (xSemaphoreTake(socket_mutex, pdMS_TO_TICKS(100)) == pdPASS) {
        int ret = send(tcp_socket, heartbeat, len, 0);
        if (ret < 0) {
            ESP_LOGE(TAG, "Heartbeat send error: %s", strerror(errno));
            // 发送失败直接断开连接
            set_connection_state(TCP_STATE_FAILED);
            close(tcp_socket);
            tcp_socket = -1;
        } else {
            ESP_LOGD(TAG, "Heartbeat sent (%d bytes)", ret);
        }
        xSemaphoreGive(socket_mutex);
    }
}

// 停止心跳定时器
static void tcp_stop_heartbeat(void) {
    if (heartbeat_timer) {
        xTimerStop(heartbeat_timer, pdMS_TO_TICKS(100));
        xTimerDelete(heartbeat_timer, pdMS_TO_TICKS(100));
        heartbeat_timer = NULL;
    }
    ESP_LOGI(TAG, "Heartbeat stopped");
}

// 连接到服务器
static bool tcp_connect_to_server(void) {
    struct sockaddr_in dest_addr;
    
    if (tcp_socket >= 0) {
        close(tcp_socket);
        tcp_socket = -1;
    }
    
    tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (tcp_socket < 0) {
        ESP_LOGE(TAG, "Failed to create socket");
        return false;
    }
    
    dest_addr.sin_addr.s_addr = inet_addr(server_ip);
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(server_port);
    
    // 设置TCP_NODELAY禁用Nagle算法
    int flag = 1;
    setsockopt(tcp_socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
    
    // 设置连接超时
    struct timeval timeout = {
        .tv_sec = 5,
        .tv_usec = 0
    };
    setsockopt(tcp_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
    setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    
    // 连接服务器
    ESP_LOGI(TAG, "Connecting to %s:%d...", server_ip, server_port);
    int ret = connect(tcp_socket, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    if (ret != 0) {
        ESP_LOGE(TAG, "Connect failed: %s", strerror(errno));
        close(tcp_socket);
        tcp_socket = -1;
        return false;
    }
    
    ESP_LOGI(TAG, "Connected to server %s:%d", server_ip, server_port);
    tcp_start_heartbeat();
    return true;
}

// 启动心跳定时器
static void tcp_start_heartbeat(void) {
    tcp_stop_heartbeat(); // 确保之前定时器已停止
    
    // 创建心跳发送定时器
    heartbeat_timer = xTimerCreate(
        "tcp_heartbeat",
        pdMS_TO_TICKS(client_config.heartbeat_interval_ms),
        pdTRUE,
        NULL,
        tcp_send_heartbeat
    );
    
    if (!heartbeat_timer) {
        ESP_LOGE(TAG, "Failed to create heartbeat timer");
        return;
    }
    
    if (xTimerStart(heartbeat_timer, pdMS_TO_TICKS(100)) != pdPASS) {
        ESP_LOGE(TAG, "Failed to start heartbeat timer");
        tcp_stop_heartbeat();
        return;
    }
    
    ESP_LOGI(TAG, "Heartbeat started (interval: %dms)", 
             client_config.heartbeat_interval_ms);
}

// TCP发送任务
static void tcp_send_task(void *pvParameters) {
    TcpPacket packet;
    
    while (1) {
        // 检查队列中是否有数据
        if (xQueueReceive(send_queue, &packet, pdMS_TO_TICKS(100)) == pdPASS) {
            if (tcp_get_connection_state() == TCP_STATE_CONNECTED) {
                // 加锁保护socket操作
                if (xSemaphoreTake(socket_mutex, portMAX_DELAY) == pdPASS) {
                    int bytes_sent = send(tcp_socket, packet.data, packet.length, 0);
                    if (bytes_sent < 0) {
                        ESP_LOGE(TAG, "Send failed! errno=%d", errno);
                        set_connection_state(TCP_STATE_FAILED);
                        close(tcp_socket);
                        tcp_socket = -1;
                    } else {
                        ESP_LOGI(TAG, "Sent %d bytes", bytes_sent);
                    }
                    xSemaphoreGive(socket_mutex);
                }
            }
            
            // 释放数据包内存
            if (!packet.is_dma && packet.data) {
                free(packet.data);
            }
        }
        
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

// TCP接收任务
static void tcp_recv_task(void *pvParameters) {
    uint8_t *rx_buffer = malloc(client_config.recv_buffer_size);
    if (!rx_buffer) {
        ESP_LOGE(TAG, "Failed to allocate receive buffer");
        vTaskDelete(NULL);
    }
    
    while (1) {
        switch (tcp_get_connection_state()) {
            case TCP_STATE_CONNECTED: {
                // 设置接收超时
                struct timeval tv = {
                    .tv_sec = client_config.reconnect_interval_ms / 1000,
                    .tv_usec = (client_config.reconnect_interval_ms % 1000) * 1000
                };
                setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
                
                // 加锁接收数据
                int bytes_received = 0;
                if (xSemaphoreTake(socket_mutex, portMAX_DELAY) == pdPASS) {
                    bytes_received = recv(tcp_socket, rx_buffer, client_config.recv_buffer_size - 1, 0);
                    xSemaphoreGive(socket_mutex);
                }
                
                if (bytes_received > 0) {
                    rx_buffer[bytes_received] = '\0';
                    ESP_LOGI(TAG, "Received %d bytes: %.*s", 
                             bytes_received, bytes_received, rx_buffer);
                    
                    // 检查是否是欢迎信息
                    bool is_welcome = (bytes_received == welcome_msg_len) && 
                                      (memcmp(rx_buffer, welcome_message, welcome_msg_len) == 0);
                    
                    if (!is_welcome) {
                        process_received_data(rx_buffer, bytes_received);
                    }
                } 
                else if (bytes_received == 0) {
                    ESP_LOGI(TAG, "Server closed connection");
                    set_connection_state(TCP_STATE_FAILED);
                    close(tcp_socket);
                    tcp_socket = -1;
                    tcp_stop_heartbeat();
                }
                else if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    ESP_LOGE(TAG, "Receive error! errno=%d", errno);
                    set_connection_state(TCP_STATE_FAILED);
                    close(tcp_socket);
                    tcp_socket = -1;
                    tcp_stop_heartbeat();
                }
                break;
            }
            
            case TCP_STATE_DISCONNECTED:
            case TCP_STATE_FAILED:
                // 尝试重新连接
                if (server_ip && server_port > 0) {
                    set_connection_state(TCP_STATE_CONNECTING);
                    if (tcp_connect_to_server()) {
                        set_connection_state(TCP_STATE_CONNECTED);
                    } else {
                        set_connection_state(TCP_STATE_FAILED);
                    }
                }
                vTaskDelay(pdMS_TO_TICKS(client_config.reconnect_interval_ms));
                break;
                
            case TCP_STATE_CONNECTING:
                // 等待连接完成
                vTaskDelay(pdMS_TO_TICKS(100));
                break;
        }
        
        vTaskDelay(pdMS_TO_TICKS(10));
    }
    
    free(rx_buffer);
}

// 公共接口实现
void tcp_client_init(const TcpClientConfig *config) {
    if (config) {
        memcpy(&client_config, config, sizeof(TcpClientConfig));
    } else {
        memcpy(&client_config, &DEFAULT_CONFIG, sizeof(TcpClientConfig));
    }
    
    // 创建状态互斥锁
    if (!state_mutex) {
        state_mutex = xSemaphoreCreateMutex();
    }
    
    set_connection_state(TCP_STATE_DISCONNECTED);
}

void tcp_client_start(const char *ip, int port) {
    // 清理旧连接
    if (server_ip) {
        free(server_ip);
    }
    
    server_ip = strdup(ip);
    server_port = port;
    
    // 创建发送队列
    if (!send_queue) {
        send_queue = xQueueCreate(client_config.send_queue_size, sizeof(TcpPacket));
    }
    
    // 创建socket互斥锁
    if (!socket_mutex) {
        socket_mutex = xSemaphoreCreateMutex();
    }
    
    // 启动任务
    if (!send_task_handle) {
        xTaskCreate(tcp_send_task, "tcp_send_task", 4096, NULL, 3, &send_task_handle);
    }
    
    if (!recv_task_handle) {
        xTaskCreate(tcp_recv_task, "tcp_recv_task", 4096, NULL, 3, &recv_task_handle);
    }
    
    // 开始连接
    set_connection_state(TCP_STATE_CONNECTING);
}

void tcp_client_stop(void) {
    set_connection_state(TCP_STATE_DISCONNECTED);
    tcp_stop_heartbeat();
    
    if (send_task_handle) {
        vTaskDelete(send_task_handle);
        send_task_handle = NULL;
    }
    
    if (recv_task_handle) {
        vTaskDelete(recv_task_handle);
        recv_task_handle = NULL;
    }
    
    if (tcp_socket >= 0) {
        close(tcp_socket);
        tcp_socket = -1;
    }
    
    if (server_ip) {
        free(server_ip);
        server_ip = NULL;
    }
    
    if (send_queue) {
        vQueueDelete(send_queue);
        send_queue = NULL;
    }
}

bool tcp_send_data(const uint8_t *data, size_t len, TickType_t timeout) {
    if (!send_queue || len == 0) {
        return false;
    }
    
    // 检查连接状态
    if (tcp_get_connection_state() != TCP_STATE_CONNECTED) {
        ESP_LOGW(TAG, "Send failed: not connected");
        return false;
    }
    
    // 检查队列状态
    if (uxQueueMessagesWaiting(send_queue) >= client_config.send_queue_size) {
        ESP_LOGW(TAG, "Send queue full, discarding packet");
        return false;
    }
    
    // 创建数据包副本
    TcpPacket packet;
    packet.data = malloc(len);
    if (!packet.data) {
        return false;
    }
    memcpy(packet.data, data, len);
    packet.length = len;
    packet.is_dma = false;
    
    // 发送到队列
    if (xQueueSend(send_queue, &packet, timeout) != pdPASS) {
        free(packet.data);
        return false;
    }
    
    return true;
}

TcpConnectionState tcp_get_connection_state(void) {
    TcpConnectionState state;
    xSemaphoreTake(state_mutex, portMAX_DELAY);
    state = connection_state;
    xSemaphoreGive(state_mutex);
    return state;
}

void tcp_client_update_config(const TcpClientConfig *new_config) {
    if (!new_config) return;
    
    xSemaphoreTake(state_mutex, portMAX_DELAY);
    // 保留原有配置更新逻辑
    uint32_t old_interval = client_config.heartbeat_interval_ms;
    memcpy(&client_config, new_config, sizeof(TcpClientConfig));
    xSemaphoreGive(state_mutex);
    
    // 如果心跳间隔改变且已连接，重启心跳
    if (heartbeat_timer && 
        tcp_get_connection_state() == TCP_STATE_CONNECTED &&
        old_interval != client_config.heartbeat_interval_ms) 
    {
        tcp_stop_heartbeat();
        tcp_start_heartbeat();
    }
    
    ESP_LOGI(TAG, "Client configuration updated");
}

// 发送答题结果
int send_answer_result(int question_number, int result_flag) {
    // 使用动态缓冲区
    char *json_buffer = NULL;
    int json_length = snprintf(NULL, 0, 
        "{\"questionId\":%d,\"correct\":%s}", 
        question_number, 
        result_flag == CORRECT ? "true" : "false");
    
    if (json_length <= 0) {
        ESP_LOGE(TAG, "JSON formatting failed");
        return -2;
    }
    
    json_buffer = malloc(json_length + 1);
    if (!json_buffer) {
        return -3;
    }
    
    snprintf(json_buffer, json_length + 1,
        "{\"questionId\":%d,\"correct\":%s}", 
        question_number, 
        result_flag == CORRECT ? "true" : "false");
    
    // 发送数据（带超时）
    bool success = tcp_send_data((uint8_t*)json_buffer, json_length, 
                               pdMS_TO_TICKS(client_config.send_timeout_ms));
    
    free(json_buffer);
    
    if (!success) {
        ESP_LOGE(TAG, "TCP send failed");
        return -4;
    }
    
    ESP_LOGI(TAG, "Answer result sent: Q%d %s", 
             question_number, result_flag == CORRECT ? "CORRECT" : "INCORRECT");
    return 0;
}

void process_question_result(void) {
    // 获取答题结果标志
    int flag = get_question_result_flag(); 
    ESP_LOGI(TAG, "Question result flag: %d", flag);
    
    // 获取问题编号
    int question_number = get_questionNum();
    // 只有在答题正确且问题编号有效时才发送
    if (flag == CORRECT && question_number >= 1) {
        int result = send_answer_result(question_number, flag);
        
        if (result > 0) {
            ESP_LOGI(TAG, "Answer result sent successfully");
            printf("Answer result sent successfully\n");
        } else {
            ESP_LOGE(TAG, "Failed to send answer result: %d", result);
        }
    }
}